﻿using System;
using System.Reflection;

namespace EP.Utilities {
	public abstract class Singleton<C, I>
		where C : class, I
		where I : class {
		private static I _instance;
		private static readonly object padlock = new object();

		public static I Instance { get { return _instance ?? (_instance = CreateInstance()); } }

		protected static I CreateInstance() {
			lock (padlock) {
				var type = typeof(C);

				// Ensure there are no public constructors...
				ConstructorInfo[] ctors = type.GetConstructors();
				if (ctors.Length > 0) {
					throw new InvalidOperationException(String.Format("{0} has at least one accesible ctor making it impossible to enforce singleton behaviour", type.Name));
				}

				// Create an instance via the private constructor
				var constructorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, Type.EmptyTypes, null);
				if (constructorInfo == null)
					throw new ArgumentException(string.Format("{0} does not have a parameterless constructor", type.Name));

				return Activator.CreateInstance(type, true) as I;
			}
		}
	}
}
